package com.leoman.service.impl;

import com.leoman.controller.common.CommonController;
import com.leoman.core.Constant;
import com.leoman.dao.AppUserDao;
import com.leoman.dao.AppUserGainDao;
import com.leoman.entity.AppUserGain;
import com.leoman.entity.vo.AppUserGainPlusVo;
import com.leoman.entity.vo.AppUserGainVo;
import com.leoman.exception.ParamErrorException;
import com.leoman.exception.UserNotFindException;
import com.leoman.exception.UserSealStatusException;
import com.leoman.service.AppUserGainService;
import com.leoman.utils.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * AppUserGainImpl
 * Created by 涂奕恒 on 2016/10/18 0018 下午 3:15.
 */
@Service
public class AppUserGainServiceImpl implements AppUserGainService {

    @Autowired
    private AppUserGainDao appUserGainDao;

    @Autowired
    private AppUserDao appUserDao;

    @Override
    public List<AppUserGain> findAll() {
        return appUserGainDao.findAll();
    }

    @Override
    public Page<AppUserGain> find(int pageNum, int pageSize) {
        return appUserGainDao.findAll(new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    public Page<AppUserGain> find(int pageNum) {
        return find(pageNum, Constant.PAGE_DEF_SIZE);
    }

    @Override
    public AppUserGain getById(int id) {
        return appUserGainDao.findOne(id);
    }

    @Override
    public void deleteById(int id) {
        appUserGainDao.delete(id);
    }

    @Override
    public AppUserGain create(AppUserGain appUserGain) {
        return appUserGainDao.save(appUserGain);
    }

    @Override
    public AppUserGain update(AppUserGain appUserGain) {
        return appUserGainDao.save(appUserGain);
    }

    @Override
    @Transactional
    public void deleteAll(int[] ids) {
        for (int id : ids) {
            deleteById(id);
        }
    }

    @Override
    public List<AppUserGainVo> iFindListRankInfoByIndex(Integer index) {
        Double baseMoney = 0.0;
        List<AppUserGain> tempGainList;
        AppUserGainVo userGainVo;

        if (null == index) {
            index = Constant.rankIndex;
        }

        List<AppUserGainVo> list = new ArrayList<>();

        // 先将所有用户分组
        List<AppUserGain> gainList = appUserGainDao.iGroupByAppUserForRank();

        // 取前几名的数据
        if (null == gainList || gainList.size() == 0) {
            return list;
        } else if (index >= gainList.size()) {
            index = gainList.size();
        }

        // 然后获取每个用户的总收益金额
        for (int i = 0; i < index; i++) {
            tempGainList = appUserGainDao.iFindListOnlyGainByUserId(gainList.get(i).getAppUser().getId());
            for (AppUserGain userGain : tempGainList) {
                baseMoney += userGain.getMoney();
            }
            userGainVo = new AppUserGainVo();
            userGainVo.setId(gainList.get(i).getAppUser().getId());
            userGainVo.setNickName(gainList.get(i).getAppUser().getNickName());
            userGainVo.setAvatar(gainList.get(i).getAppUser().getAvatar());
            userGainVo.setMoney(baseMoney);

            list.add(userGainVo);

            baseMoney = 0.0;
        }

        Collections.sort(list, new Comparator<AppUserGainVo>() {
            /*
             * int compare(Student o1, Student o2) 返回一个基本类型的整型，
             * 返回负数表示：o1 小于o2，
             * 返回0 表示：o1和o2相等，
             * 返回正数表示：o1大于o2。
             */
            public int compare(AppUserGainVo o1, AppUserGainVo o2) {
                // 按照总收益金额进行降序排列
                if (o1.getMoney() > o2.getMoney()) {
                    return -1;
                }
                if (o1.getMoney().equals(o2.getMoney())) {
                    return 0;
                }
                return 1;
            }
        });

        return list;
    }

    @Override
    public List<AppUserGainVo> iFindListDynamicByIndex(Integer index) {
        List<AppUserGainVo> list = new ArrayList<>();
        AppUserGainVo userGainVo;

        if (null == index) {
            index = Constant.rankIndex;
        }

        List<AppUserGain> gainList = appUserGainDao.iFindListOnlyGain();

        // 取前几名的数据
        if (null == gainList || gainList.size() == 0) {
            return list;
        } else if (index >= gainList.size()) {
            index = gainList.size();
        }

        for (int i = 0; i < index; i++) {
            userGainVo = new AppUserGainVo();
            userGainVo.setId(gainList.get(i).getId());
            userGainVo.setNickName(gainList.get(i).getAppUser().getNickName());
            userGainVo.setAvatar(gainList.get(i).getAppUser().getAvatar());
            userGainVo.setMoney(gainList.get(i).getMoney());

            list.add(userGainVo);
        }

        return list;
    }

    @Override
    public Page<AppUserGain> iPageByUserId(Integer userId, Integer pageNum, Integer pageSize) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        AppUserServiceImpl.getAppUserInfo(userId, appUserDao);
        Integer[] info = CommonController.getPageParams(pageNum, pageSize);
        Page<AppUserGain> page = appUserGainDao.iPageByUserId(userId, new PageRequest(info[0] - 1, info[1]));

        for (AppUserGain appUserGain : page.getContent()) {
            appUserGain.setMonth(appUserGain.getRecordDate());
            appUserGain.setGainList(changeList(appUserGainDao.findListByRecordDate(userId, appUserGain.getRecordDate())));
        }

        return page;
    }

    private List<AppUserGainPlusVo> changeList(List<AppUserGain> appUserGainList) {
        List<AppUserGainPlusVo> list = new ArrayList<>();
        AppUserGainPlusVo appUserGainPlusVo;

        for (AppUserGain appUserGain : appUserGainList) {
            appUserGainPlusVo = new AppUserGainPlusVo();
            appUserGainPlusVo.setGainId(appUserGain.getId());
            appUserGainPlusVo.setGainContent(appUserGain.getContent());
            appUserGainPlusVo.setGainMoney(appUserGain.getMoney());
            appUserGainPlusVo.setGainCreateTime(appUserGain.getCreateTime());

            list.add(appUserGainPlusVo);
        }

        return list;
    }

    @Override
    public Page<AppUserGain> pageByParams(final Integer gainId, final String nickName, final String aliPayAccount, final Integer requestStatus, Integer pageNum, Integer pageSize) {
        Integer[] info = CommonController.getPageParams(pageNum, pageSize);

        return appUserGainDao.findAll(new Specification<AppUserGain>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<AppUserGain> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();
                if (null != gainId) {
                    Predicate pre = cb.equal(root.get("id").as(Integer.class), gainId);
                    predicateList.add(pre);
                }
                if (StringUtils.isNotBlank(nickName)) {
                    Predicate pre = cb.like(root.get("appUser").get("nickName").as(String.class), "%" + nickName + "%");
                    predicateList.add(pre);
                }
                if (StringUtils.isNotBlank(aliPayAccount)) {
                    Predicate pre = cb.like(root.get("appUser").get("aliPayAccount").as(String.class), "%" + aliPayAccount + "%");
                    predicateList.add(pre);
                }
                if (null != requestStatus) {
                    Predicate pre = cb.equal(root.get("requestStatus").as(Integer.class), requestStatus);
                    predicateList.add(pre);
                }

                Predicate pre1 = cb.equal(root.get("content").as(String.class), Constant.APP_USER_GIVE_MONEY_CONTENT);
                predicateList.add(pre1);

                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, new PageRequest(info[0] - 1, info[1], Sort.Direction.ASC, "requestStatus"));
    }

    @Override
    public Integer confirmMoney(Integer gainId) {
        try {
            AppUserGain appUserGain = appUserGainDao.findOne(gainId);

            if (null != appUserGain) {
                if (appUserGain.getRequestStatus().equals(Constant.GIVE_MONEY_STATUS_YES)) {
                    return -1;
                }

                appUserGain.setRequestStatus(Constant.GIVE_MONEY_STATUS_YES);

                appUserGainDao.save(appUserGain);

                return 1;
            }

            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Integer getGainCountByUserId(Integer userId) {
        try {
            Long startTime = DateUtils.stringToDateWithFormat(DateUtils.dateToStringWithFormat(new Date(), "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd hh:mm:ss").getTime();
            Long endTime = DateUtils.stringToDateWithFormat(DateUtils.dateToStringWithFormat(new Date(), "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd hh:mm:ss").getTime();

            return appUserGainDao.findListByParams(userId, startTime, endTime).size();
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}